package com.erlang4j.api;

import com.erlang4j.api.exceptionHandler.IExceptionHandler;
import com.erlang4j.api.process.IProcess;
import com.erlang4j.internal.messages.IMessageComposer;
import com.erlang4j.internal.messages.IMessageHandler;
import com.erlang4j.internal.messages.IMessageParser;
import com.erlang4j.internal.stateMachine.IStateDefinition;

/**
 * <p>
 * This interface exists to provide access to the features provides by Erlang4j. If you want to make one of these, go
 * via the Erlang4JFactory.
 * <ul>
 * <li>If you only want to send things to erlang, or use very simple RPC then this can be used directly.
 * <li>If you want to have either more than one "process" on the java side, or have more complex communication
 * requirements then the "spawn" method is useful.
 * <li>If you are implementing a complex protocol with state, then the state machines is useful.
 * </ul>
 * </p>
 * The spawn method is the equivalent of a spawn(fun()->loop(Params)) in Erlang. </p>
 * <p>The spawnStateMachine method is the equivalent of a state machine in Erlang</p.S
 * 
 * <p>
 * Design notes
 * <ul>
 * <li>This is a stateful object: it acts as a node (Erlang Virtual Machine)
 * <li>This is a facade to provide the Erlang4J facilities as a single interface
 * <li>This allows the user of the api to use code insight as a discovery mechanism for finding what they do
 * <li>This also allows us to later use different implementation such as the debugging, profiling, logging etc
 * IErlang4J.
 * </ul>
 * </p>
 * 
 * @author Phil Rice
 */
public interface IErlang4j extends IMessageParser, IMessageComposer, IMailBox {

	/**
	 * This is the equivalent of defining a loop function in erlang. The result is that you have an IProcess with its
	 * own mailbox. This can be used to send or receive data from Erlang. If you specified any handlers, a thread will
	 * be spawned that receives messages and passes them to the correct handler. If you pass no message handlers in then
	 * the IProcess can be used as in for send and receive.
	 */
	IProcess spawn(IMessageHandler... handlers);

	/**
	 * this spawns a process that at any time is in one state. When in a state it is using the message handlers of that
	 * state. Those message handlers can change the state. The state machines has a matching binding that it uses to
	 * keep "state" (overloaded word) in. Every time a message comes in, the matching binding is included in the message
	 * handler pattern matching. This binding is available from the IProcessWithState passed to the message handlers.
	 * The message handlers can modify this state (the modifications are only visible after the message handler exits.
	 * This models very closely how Erlang can implement state machines, and is very useful when designing protocols
	 * more complex than a simple command / reply
	 */
	IProcess spawnStateMachine(IStateDefinition... stateDefinitions);

	/** the exception handler that will be used to report exceptions */
	IExceptionHandler exceptionHandler();

}
